using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
using AutumnEngine.Modules;
using System.IO;

namespace AutumnEngine
{
    public partial class Scene
    {
        /// <summary>
        /// Loads the scene from the specified path.
        /// </summary>
        /// <param name="path">The path.</param>
        public void Load(string path)
        {
            //Clear scene
            this.Nodes.Clear();
            if (Engine.Modules.Contains("Engine.PhysicsManager"))
                Engine.Modules.PhysicsManager.RemoveSimNodes(this.ID);

            int labelCount, nodeCount, markerCount, physCount, spriteCount;
            /*
             * create binary reader
             * foreach stage (type of node)
             * read number
             * if number = 0, skip, otherwise
             * read all names
             * read all textures
             * read all X pos
             * read all Y pos
             * read all R
             * B
             * G
             * A
             * read all rotation
             * read all scale
             * repeat for all stages
             * read names of all used stages
             * read their paths
            */

            //Open
            string fix = "";
            if (path.Contains(@":\"))
            {
                //This is a full path
                fix = path;
            }
            else
            {
                fix = StorageContainer.TitleLocation + "/" + path;

            }
            FileStream fs = File.OpenRead(fix);
            BinaryReader reader = new BinaryReader(fs);
            Dictionary<string, Node> nodes = new Dictionary<string, Node>();
            Dictionary<string, Marker> markers = new Dictionary<string, Marker>();
            Dictionary<string, SpriteNode> spriteNodes = new Dictionary<string, SpriteNode>();
            Dictionary<string, PhysicsSpriteNode> physicsSpriteNodes = new Dictionary<string, PhysicsSpriteNode>();
            Dictionary<string, LabelNode> labels = new Dictionary<string, LabelNode>();
            List<string> nodeNames,markerNames,spriteNames,physNames;
            List<bool> nodeTr,markerTr,spriteTr,physTr;
            List<Vector2> nodePositons, markerPositions, spritePositions, physPositions;
            ///////////////////
            //Read 'Nodes'
            int count = reader.ReadInt32();
            nodeCount = count;
            nodePositons = new List<Vector2>();
            nodeNames = new List<string>();
            nodeTr = new List<bool>();
            if (count != 0)
            {
               
                for (int i = 0; i < count; i++)
                {
                    nodeNames.Add(reader.ReadString());
                    nodePositons.Add(new Vector2((float)reader.ReadInt32(), (float)reader.ReadInt32()));                    
                    nodeTr.Add(reader.ReadBoolean());
                    
                }
            }

            //Read markers
            count = reader.ReadInt32();
            markerCount = count;
            markerNames = new List<string>();
            markerPositions = new List<Vector2>();
            markerTr = new List<bool>();
            if (count != 0)
            {
               
                for (int i = 0; i < count; i++)
                {
                    markerNames.Add(reader.ReadString());
                    Marker tmp = new Marker();
                    markerPositions.Add(new Vector2((float)reader.ReadInt32(), (float)reader.ReadInt32()));
                    markerTr.Add(reader.ReadBoolean());
                }
            }

            //SpriteNodes
            //Formwat
            /*
             * Pos X
             * Pos Y
             * StrTexture
             * Scale X
             * Scale Y
             * Rotation
             * Origin X
             * Origin Y
             * Color R
             * Color G
             * Color B
             * Color A
            */
            spriteNames = new List<string>();
            spriteTr = new List<bool>();
            spritePositions = new List<Vector2>();
            List<string> spriteTextures = new List<string>();
            List<Vector2> spriteScales = new List<Vector2>();
            List<float> spriteRots = new List<float>();
            List<Vector2> spriteOrig = new List<Vector2>();
            List<Color> spriteColor = new List<Color>();

            count = reader.ReadInt32();
            spriteCount = count;

            if (count != 0)
            {
                for (int i = 0; i < count; i++)
                {
                   spriteNames.Add(reader.ReadString());
                    int x = reader.ReadInt32();
                    int y = reader.ReadInt32();
                    spriteTextures.Add(reader.ReadString());
                    spritePositions.Add(new Vector2(x, y));
                    Vector2 scale = new Vector2(reader.ReadInt32(), reader.ReadInt32());
                    spriteScales.Add(scale);
                    float rot = (float)reader.ReadDouble();
                    spriteRots.Add(rot);
                    Vector2 or = new Vector2(reader.ReadInt32(), reader.ReadInt32());
                    spriteOrig.Add(or);
                    Color c = new Color(reader.ReadByte(), reader.ReadByte(), reader.ReadByte(), reader.ReadByte());
                    spriteColor.Add(c);
                    spriteTr.Add(reader.ReadBoolean());
                }
            }

            //Physics sprite nodes
            //Formwat
            /*
             * Pos X
             * Pos Y
             * StrTexture
             * Scale X
             * Scale Y
             * Rotation
             * Origin X
             * Origin Y
             * Color R
             * Color G
             * Color B
             * Color A
             * byte BodyType
             * int width
             * int height
             * double mass
             * bool static
            */

            physNames = new List<string>();
            physTr = new List<bool>();
            physPositions = new List<Vector2>();
            List<string> physTextures = new List<string>();
            List<Vector2> physScales = new List<Vector2>();
            List<float> physRots = new List<float>();
            List<Vector2> physOrig = new List<Vector2>();
            List<Color> physColor = new List<Color>();
            List<BodyType> bodyTypes = new List<BodyType>();
            List<int> widths = new List<int>();
            List<int> heights = new List<int>();
            List<float> masses = new List<float>();
            List<bool> statics = new List<bool>();

            count = reader.ReadInt32();
            physCount = count;
            if (count != 0)
            {
                for (int i = 0; i < count; i++)
                {
                    physNames.Add(reader.ReadString());
                    int x = reader.ReadInt32();
                    int y = reader.ReadInt32();
                    physPositions.Add(new Vector2(x, y));                    
                    physTextures.Add(reader.ReadString());

                    physScales.Add(new Vector2(reader.ReadInt32(), reader.ReadInt32()));
                    physRots.Add((float)reader.ReadDouble());
                    physOrig.Add(new Vector2(reader.ReadInt32(), reader.ReadInt32()));
                    Color c = new Color(reader.ReadByte(), reader.ReadByte(), reader.ReadByte(), reader.ReadByte());
                    physColor.Add(c);
                    BodyType type = (BodyType)reader.ReadByte();
                    bodyTypes.Add(type);
                   widths.Add(reader.ReadInt32());
                   heights.Add(reader.ReadInt32());
                   masses.Add((float)reader.ReadDouble());
                    
                   statics.Add(reader.ReadBoolean());
                   physTr.Add(reader.ReadBoolean());
                }
            }

            //Labels
            //Formwat
            /*
             * Pos X
             * Pos Y
             * StrText
             * StrFont
             * dobule scale
             * Rotation
             * Origin X
             * Origin Y
             * Color R
             * Color G
             * Color B
             * Color A
            */
            count = reader.ReadInt32();
            labelCount = count;
            List<string> labNames = new List<string>();
            List<Vector2> labPos = new List<Vector2>();
            List<string> textCont = new List<string>();
            List<string> labFonts = new List<string>();
            List<float> scales = new List<float>();
            List<float> rotations = new List<float>();
            List<Vector2> labOrig = new List<Vector2>();
            List<Color> labColors = new List<Color>();
            List<bool> labTR = new List<bool>();
            if (count != 0)
            {
                for (int i = 0; i < count; i++)
                {
                    labNames.Add(reader.ReadString());
                    int x = reader.ReadInt32();
                    int y = reader.ReadInt32();
                    labPos.Add(new Vector2(x, y));
                    textCont.Add(reader.ReadString());
                    labFonts.Add(reader.ReadString());
                    scales.Add((float)reader.ReadDouble());
                    rotations.Add((float)reader.ReadDouble());
                   labOrig.Add(new Vector2(reader.ReadInt32(), reader.ReadInt32()));
                    Color c = new Color(reader.ReadByte(), reader.ReadByte(), reader.ReadByte(), reader.ReadByte());
                    labColors.Add(c);
                    labTR.Add(reader.ReadBoolean());
                }
            }


            //Texture name/path combos
            List<string> paths, names;
            paths = new List<string>();
            names = new List<string>();
            int co = reader.ReadInt32();
            if (co != 0)
            {
                for (int i = 0; i < co; i++)
                {
                    string v = reader.ReadString();
                    names.Add(v);
                }
                paths = new List<string>();
                for (int i = 0; i < co; i++)
                {
                    string v = reader.ReadString();
                    paths.Add(v);
                }
                if (names.Count > 0 && paths.Count > 0)
                {
                    for (int i = 0; i < co; i++)
                    {
                        //Load the textures
                        Engine.Modules.TextureManager.AddTexture(names[i], paths[i]);
                    }
                }
            }
            paths.Clear();
            names.Clear();
            //Font name/path combos
            int p = reader.ReadInt32();
            if (p != 0)
            {
                for (int i = 0; i < p; i++)
                {
                    string v = reader.ReadString();
                    names.Add(v);
                }
                
                for (int i = 0; i < p; i++)
                {
                    string v = reader.ReadString();
                    paths.Add(v);
                }
            }

            if (names.Count > 0)
            {
                for (int i = 0; i < p; i++)
                {
                    //Load the fonts
                    System.Diagnostics.Debug.WriteLine("Adding font " + names[i] + ":" + paths[i]);

                    Engine.Modules.FontManager.AddFont(names[i], paths[i]);
                }
            }

            for (int i = 0; i < nodeCount; i++)
            {
                Node tmp = new Node();
                tmp.CameraTranslation = nodeTr[i];
                tmp.Position = nodePositons[i];
                this.AddNode(nodeNames[i], tmp);
            }

            for (int i = 0; i < markerCount; i++)
            {
                Marker tmp = new Marker();
                tmp.Position = markerPositions[i];
                tmp.CameraTranslation = markerTr[i];
                this.AddNode(markerNames[i], tmp);
            }
            for (int i = 0; i < spriteCount; i++)
            {
                SpriteNode tmp = new SpriteNode(spriteTextures[i]);
                Engine.Modules.Logging.Write(tmp.Texture, LogLevel.Debug);
                tmp.CameraTranslation = spriteTr[i];
                tmp.Color = spriteColor[i];
                tmp.Origin = spriteOrig[i];
                tmp.Position = spritePositions[i];
                tmp.Rotation = spriteRots[i];
                tmp.Scale = spriteScales[i];
                this.AddNode(spriteNames[i], tmp);
            }

            for (int i = 0; i < physCount; i++)
            {
                PhysicsSpriteNode tmp = new PhysicsSpriteNode(physTextures[i], bodyTypes[i], widths[i], heights[i], masses[i]);
                tmp.CameraTranslation = physTr[i];
                tmp.Color = physColor[i];
                tmp.Position = physPositions[i];
                tmp.Rotation = physRots[i];
                tmp.Scale = physScales[i];
                tmp.Static = statics[i];
                this.AddNode(physNames[i], tmp);
            }

            for (int i = 0; i < labelCount; i++)
            {
                LabelNode tmp = new LabelNode(labFonts[i]);
                tmp.CameraTranslation = labTR[i];
                tmp.Color = labColors[i];
                tmp.Origin = labOrig[i];
                tmp.Position = labPos[i];
                tmp.Rotation = rotations[i];
                tmp.Scale = scales[i];
                tmp.Text = textCont[i];
                this.AddNode(labNames[i], tmp);
            }
            ///////////////////
            //Close
            reader.Close();            
            fs.Close();
            
        }
    }
}